package com.zdxlz.fcmp.common.security.filter;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.zdxlz.fcmp.common.core.exception.BizException;
import com.zdxlz.fcmp.common.security.util.GlobalHttpServletRequestWrapper;
import jakarta.annotation.Resource;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Iterator;

import static com.zdxlz.fcmp.common.core.constant.CommonConstants.*;

/**
 * @Description：参数转换过滤器
 * @Author： aman
 * @Date： 2025/2/12 10:49
 */
@Slf4j
@Component
@AllArgsConstructor
public class ParameterConversionFilter implements Filter {

    @Resource
    private RequestMappingHandlerMapping handlerMapping;

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        GlobalHttpServletRequestWrapper httpServletRequestWrapper = new GlobalHttpServletRequestWrapper(request);
        String requestWay = request.getMethod();
        // 获取URL映射的处理器信息
        try {
            // 只针对GET请求中枚举参数进行转换
            if (HttpMethod.GET.name().equals(requestWay)) {
                Object handler = handlerMapping.getHandler(request);
                if (ObjectUtil.isNotEmpty(handler)) {
                    HandlerMethod handlerMethod = (HandlerMethod) (handler.getClass().equals(HandlerExecutionChain.class) ? ((HandlerExecutionChain) handler).getHandler() : handler);
                    Method method = handlerMethod.getMethod();
                    // 获取方法参数类型
                    Class<?>[] parameterTypes = method.getParameterTypes();
                    for (Class<?> paramType : parameterTypes) {
                        String name = paramType.getName();
                        if (name.endsWith(PARAMETER_SUFFIX)) {
                            Class<?> aClass = Class.forName(name);
                            Iterator<String> iterator = request.getParameterNames().asIterator();
                            while (iterator.hasNext()) {
                                String key = iterator.next();
                                String value = request.getParameter(key);
                                if (ENUM_CONVERSION_FIELD_LIST.contains(key) && StrUtil.isNotBlank(value)) {
                                    Field field = aClass.getDeclaredField(key);
                                    Type fieldType = field.getGenericType();
                                    String typeName = fieldType.getTypeName();
                                    Class<?> fieldClass = Class.forName(typeName);
                                    // 所有枚举常量
                                    Object[] enumConstants = fieldClass.getEnumConstants();
                                    for (Object enumConstant : enumConstants) {
                                        // 通过反射调用枚举中的静态方法
                                        Method getByCode = enumConstant.getClass().getDeclaredMethod(ENUM_STATIC_METHOD_NAME, Integer.class);
                                        Object invoke = getByCode.invoke(getByCode, Integer.parseInt(value));
                                        httpServletRequestWrapper.setParameter(key, invoke.toString());
                                    }
                                } else {
                                    if (REQ_BOOLEAN_FIELD.contains(key) && (REQ_STATUS_true.equals(value) || REQ_STATUS_false.equals(value))) {
                                        httpServletRequestWrapper.setParameter(key, value);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("全局参数转换发生异常,异常信息：{}", e.getMessage(), e);
            throw new BizException("全局参数转换发生异常");
        }
        filterChain.doFilter(httpServletRequestWrapper, response);
    }
}
